/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.nanosn.util.parsers.commandline;

import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;

/**
 *
 * @author selkhateeb
 */
public class CommandsRegistry implements Command {

    private List<Class<? extends Command>> commands;

    public CommandsRegistry(List<Class<? extends Command>> commands) {
        this.commands = commands;
    }

    public CommandsRegistry(Class<? extends Command>[] commands) {
        this.commands = Arrays.asList(commands);
    }

    public void addCommand(Class<? extends Command> command) {
        this.commands.add(command);
    }

    public void removeCommand(Class<? extends Command> command) {
        this.commands.remove(command);
    }

    /**
     * - It will pass all the arguments .. and will not remove the matched one
     * - If more that one match found it will run them all (Bug or feature?!!)
     * @param args
     * @throws Exception
     */
    public void run(String[] args) throws Exception {
        String arg = args[0];
        boolean foundMatch = false;
        for (Class<? extends Command> clazz : commands) {

            //The class has annotation of type argument
            Argument argument = (Argument) clazz.getAnnotation(Argument.class);
            if (argument != null) {
                if (Pattern.matches(argument.RegularExpression(), arg)) {
                    Command c = (Command) clazz.newInstance();
                    c.run(args);
                    foundMatch = true;
                }
            }
            /* Easiest case .. Class name is the same as the arg
             * and we are not going to care about upper or lower case letters
             */
            else if (clazz.getSimpleName().equalsIgnoreCase(arg)) {
                //run it and return
                Command c = (Command) clazz.newInstance();
                c.run(args);
                foundMatch = true;
            }
        }
        if (!foundMatch) {
            System.out.println("Usage: \n" + getHelp());
        }

    }

    public String getHelp() {
        String help = "";
        for (Class<? extends Command> clazz : commands) {
            try {
                Argument argument = (Argument) clazz.getAnnotation(Argument.class);
                if (argument == null) {
                    help += clazz.getSimpleName() + " ";
                }
                else {
                    help += argument.RegularExpression() + " ";
                }

                Command c = (Command) clazz.newInstance();
                help += c.getHelp() + "\n";
            }
            catch (InstantiationException ex) {
                Logger.getLogger(CommandsRegistry.class.getName()).log(Level.SEVERE, null, ex);
            }
            catch (IllegalAccessException ex) {
                Logger.getLogger(CommandsRegistry.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return help;
    }
}
